package com.lxs;

import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;
import java.io.*;
import java.net.*;
import java.util.concurrent.Executors;
import java.util.HashMap;
import java.util.Map;

public class JavaProxyServer {

    // 定义路由映射：路径前缀 -> 目标服务地址
    private static final Map<String, String> ROUTE_MAPPING = new HashMap<>();

    static {
        ROUTE_MAPPING.put("/a/", "http://localhost:9001");  // /a/ 开头的请求转发到 9001
        ROUTE_MAPPING.put("/b/", "http://localhost:9002");  // /b/ 开头的请求转发到 9002
    }

    public static void main(String[] args) throws IOException {
        int proxyPort = 8080;
        HttpServer server = HttpServer.create(new InetSocketAddress(proxyPort), 0);

        // 为每个路由前缀创建对应的处理器
        for (String routePrefix : ROUTE_MAPPING.keySet()) {
            server.createContext(routePrefix, new ProxyHandler(routePrefix));
        }

        // 添加健康检查端点
        server.createContext("/health", new HealthHandler());

        server.setExecutor(Executors.newCachedThreadPool());
        server.start();
        System.out.println("Java Proxy Server started on port " + proxyPort);
        System.out.println("路由配置: " + ROUTE_MAPPING);
    }

    static class ProxyHandler implements HttpHandler {
        private final String routePrefix;
        private final String targetBaseUrl;

        public ProxyHandler(String routePrefix) {
            this.routePrefix = routePrefix;
            this.targetBaseUrl = ROUTE_MAPPING.get(routePrefix);
        }

        @Override
        public void handle(HttpExchange exchange) throws IOException {
            String method = exchange.getRequestMethod();
            String path = exchange.getRequestURI().getPath();
            String query = exchange.getRequestURI().getQuery();

            System.out.println("==============一个请求==============");
            System.out.println("请求方法：" + method);
            System.out.println("请求路径：" + path);
            System.out.println("路由前缀：" + routePrefix);
            System.out.println("目标服务：" + targetBaseUrl);

            // 移除路由前缀
            String targetPath = path.substring(routePrefix.length() - 1); // 保留最后的斜杠

            // 构建目标URL（包含查询参数）
            String targetUrl = targetBaseUrl + targetPath;
            if (query != null && !query.isEmpty()) {
                targetUrl += "?" + query;
            }

            System.out.println("转发路径：" + targetPath);
            System.out.println("实际请求地址：" + targetUrl);

            InputStream responseStream = null;
            OutputStream responseBody = null;

            try {
                // 创建到目标服务的连接
                URL url = new URL(targetUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod(method);
                connection.setConnectTimeout(5000);  // 设置连接超时
                connection.setReadTimeout(30000);    // 设置读取超时

                // 复制请求头 - JDK 1.8 兼容写法
                for (String key : exchange.getRequestHeaders().keySet()) {
                    if (!"Host".equalsIgnoreCase(key)) {
                        for (String value : exchange.getRequestHeaders().get(key)) {
                            connection.addRequestProperty(key, value);
                        }
                    }
                }

                // 如果有请求体，复制请求体
                if ("POST".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method) || "PATCH".equalsIgnoreCase(method)) {
                    connection.setDoOutput(true);
                    OutputStream os = connection.getOutputStream();
                    InputStream is = exchange.getRequestBody();
                    copyStream(is, os);
                    os.close();
                    is.close();
                }

                // 获取响应
                int responseCode = connection.getResponseCode();
                System.out.println("响应状态码：" + responseCode);

                // 复制响应头 - JDK 1.8 兼容写法
                exchange.getResponseHeaders().clear();
                for (String key : connection.getHeaderFields().keySet()) {
                    if (key != null && !key.equals("Transfer-Encoding")) {
                        for (String value : connection.getHeaderFields().get(key)) {
                            exchange.getResponseHeaders().add(key, value);
                        }
                    }
                }

                // 发送响应头
                exchange.sendResponseHeaders(responseCode, 0);

                // 复制响应体 - JDK 1.8 兼容写法
                if (responseCode < 400) {
                    responseStream = connection.getInputStream();
                } else {
                    responseStream = connection.getErrorStream();
                }

                responseBody = exchange.getResponseBody();
                copyStream(responseStream, responseBody);

                System.out.println("请求处理完成");

            } catch (ConnectException e) {
                System.err.println("连接目标服务失败: " + targetBaseUrl);
                e.printStackTrace();
                String errorResponse = "Backend service unavailable: " + e.getMessage();
                exchange.sendResponseHeaders(503, errorResponse.length());
                try (OutputStream os = exchange.getResponseBody()) {
                    os.write(errorResponse.getBytes());
                }
            } catch (SocketTimeoutException e) {
                System.err.println("请求超时: " + targetUrl);
                e.printStackTrace();
                String errorResponse = "Request timeout: " + e.getMessage();
                exchange.sendResponseHeaders(504, errorResponse.length());
                try (OutputStream os = exchange.getResponseBody()) {
                    os.write(errorResponse.getBytes());
                }
            } catch (Exception e) {
                e.printStackTrace();
                String errorResponse = "Proxy error: " + e.getMessage();
                exchange.sendResponseHeaders(500, errorResponse.length());
                try (OutputStream os = exchange.getResponseBody()) {
                    os.write(errorResponse.getBytes());
                }
            } finally {
                // 确保流关闭
                if (responseStream != null) {
                    try { responseStream.close(); } catch (IOException e) {}
                }
                if (responseBody != null) {
                    try { responseBody.close(); } catch (IOException e) {}
                }
            }
        }

        // JDK 1.8 兼容的流复制方法
        private void copyStream(InputStream input, OutputStream output) throws IOException {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = input.read(buffer)) != -1) {
                output.write(buffer, 0, bytesRead);
            }
            output.flush();
        }
    }

    // 健康检查处理器
    static class HealthHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            String response = "{\"status\": \"ok\", \"service\": \"java-proxy-server\"}";
            exchange.getResponseHeaders().set("Content-Type", "application/json");
            exchange.sendResponseHeaders(200, response.length());
            try (OutputStream os = exchange.getResponseBody()) {
                os.write(response.getBytes());
            }
        }
    }
}
